home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / iomon2.zip / IOINIT.ASM < prev    next >
Assembly Source File  |  1992-02-20  |  20KB  |  544 lines

  1. ;---------------------------------------------------------------
  2. ;ioinit - main module for I/O Monitor                          |
  3. ;--------------------------------------------------------------|
  4. ;Copyright 1991 ASMicro Co.                                    |
  5. ;--------------------------------------------------------------|
  6. ; 5/19/91                      Rick Knoblaugh                  |
  7. ;--------------------------------------------------------------|
  8. ;include files                                                 |
  9. ;---------------------------------------------------------------
  10.                 .386P
  11.                 include ioequ.inc
  12.                 include iostruc.inc
  13.                 include iomac.inc
  14.                 include iodat.inc
  15.  
  16. ;--------------------------------------------------------------
  17. ;EXTERNALS                                                    |
  18. ;--------------------------------------------------------------
  19. isrcode         segment para public 'icode16' use16
  20.                 extrn   int_0:far
  21.                 extrn   int_2:far
  22.                 extrn   int_3:far
  23.                 extrn   int_4:far
  24.                 extrn   int_5:far
  25.                 extrn   int_6:far
  26.                 extrn   int_7:far
  27.                 extrn   except_8:far
  28.                 extrn   except_9:far
  29.                 extrn   except_0ah:far
  30.                 extrn   except_0bh:far
  31.                 extrn   except_0ch:far
  32.                 extrn   except_0dh:far
  33.                 extrn   except_0eh:far
  34.                 extrn   except_0fh:far
  35.                 extrn   int_20h:far
  36.                 extrn   int_21h:far
  37.                 extrn   int_22h:far
  38.                 extrn   int_23h:far
  39.                 extrn   int_24h:far
  40.                 extrn   int_25h:far
  41.                 extrn   int_26h:far
  42.                 extrn   int_27h:far
  43.                 extrn   int_70h:far
  44.                 extrn   int_71h:far
  45.                 extrn   int_72h:far
  46.                 extrn   int_73h:far
  47.                 extrn   int_74h:far
  48.                 extrn   int_75h:far
  49.                 extrn   int_76h:far
  50.                 extrn   int_77h:far
  51.                 extrn   int1_isr:far
  52.                 extrn   user_int_isr:far
  53. isrcode         ends
  54.  
  55.                 assume cs:code, ds:nothing, es:nothing
  56.  
  57.  
  58. code            segment para public 'code16' use16
  59.                 assume cs:code, ds:data, es:data
  60.  
  61.                 .8086
  62. start           proc    far
  63.                 push    ds              ;save psp seg
  64.                 mov     ax, data
  65.                 mov     es, ax
  66.                 call    get_args        ;get io ports
  67.                 mov     ax, data
  68.                 mov     ds, ax
  69.                 jnc     start_100       ;continue if args  ok
  70. start_050:
  71.                 mov     ah, DOS_PRT_STRING
  72.                 int     21h
  73.                 mov     ax, 4c01h
  74.                 int     21h
  75. start_100:
  76.                 call    verify_cpu
  77.                 jc      start_050       ;continue if 386/486 in real mode
  78.  
  79.                 .386P
  80. start_200:
  81.                 call    setup_ints      ;take over user int
  82.  
  83.                 call    init_gdt
  84.                 call    init_tss
  85.  
  86.                 mov     ax, data
  87.                 mov     ds, ax
  88.                 assume  ds:data
  89.  
  90.  
  91.                 cli                     ;no ints until protected mode
  92.  
  93.                 mov     ax, gdt_seg
  94.                 movzx   eax, ax
  95.                 shl     eax,  4
  96.                 mov     gdtadrs, eax
  97.  
  98.                 mov     ax, idt_seg
  99.                 movzx   eax, ax
  100.                 shl     eax,  4
  101.                 mov     idtadrs, eax
  102.  
  103.  
  104.                 call    reprogram_pic
  105.  
  106.  
  107.                 lgdt    gdtl
  108.                 lidt    idtl
  109.  
  110.                 mov     dx, iostack3    ;get stack segment
  111.                 mov     bx, sp          ;and pointer
  112.                 mov     eax, cr0
  113.                 or      eax, 1          ;turn on protected mode bit
  114.                 mov     cr0, eax        ;go into protected mode
  115.  
  116. ;
  117. ;jump to clear prefetch queue
  118. ;
  119.                 db      0eah            ;far jump
  120.                 dw      offset code:start_400
  121.                 dw      gdt_seg:sel_code
  122. start_400:
  123.                 mov     ax, offset gdt_seg:sel_tss
  124.                 ltr     ax
  125.                 xor     ax, ax
  126.                 lldt    ax              ;null ldt
  127.                 mov     ax, seg data
  128.                 movzx   eax, ax
  129.                 push    eax             ;null gs
  130.                 push    eax             ;null fs
  131.                 push    eax             ;null ds
  132.                 push    eax             ;null es
  133.  
  134.                 push    0
  135.                 push    dx              ;stack segment
  136.                 push    0
  137.                 push    bx              ;stack pointer
  138.  
  139.                 push    2               ;VM bit set in upper eflags
  140.                 push    3000h           ;NT=0, IOPL=3, CLI in lower eflags
  141.                 push    0
  142.                 push    seg code        ;cs of where to return
  143.                 push    0
  144.                 push    offset code:start_500  ;ip of where to return
  145. ;
  146. ;Must ensure that Nested Task bit is not set in eflags.  If it were,
  147. ;processor would attempt to switch to a task via the selector in
  148. ;the TSS backlink field.  Since that field is now zero, an invalid TSS
  149. ;fault would occur.
  150. ;
  151.                 pushf
  152.                 pop     ax
  153.                 and     ax, NOT NT_FLAG
  154.                 push    ax
  155.                 popf
  156.                 iretd
  157.  
  158. start_500:                              ;begin vm86 task here
  159.                 pop     bx              ;get saved psp seg
  160.                 sti                     ;interrupts ok now
  161.                 mov     dx, code + 1    ;init code we are dropping
  162.                 sub     dx, bx
  163.                 mov     al, OK          ;exit code
  164.                 mov     ah, DOS_TSR_FUNC
  165.                 int     21h
  166.  
  167. start           endp
  168.  
  169.  
  170.  
  171. reprogram_pic   proc    near
  172.                 in      al, 21h
  173.                 mov     ah, al
  174.                 mov     al, 11h         ;init
  175.                 out     20h, al
  176.                 mov     al, 20h         ;irq0 to int 20h
  177.                 out     21h, al
  178.                 jmp     short $ + 2
  179.                 jmp     short $ + 2
  180.                 mov     al, 4
  181.                 out     21h, al
  182.                 jmp     short $ + 2
  183.                 jmp     short $ + 2
  184.                 mov     al, 1
  185.                 out     21h, al
  186.                 jmp     short $ + 2
  187.                 jmp     short $ + 2
  188.                 mov     al, ah
  189.                 out     21h, al
  190.                 ret
  191. reprogram_pic   endp
  192.  
  193.  
  194.                 .8086
  195. ;--------------------------------------------------------------
  196. ;get_args - retrieve starting and ending i/o addresses from   |
  197. ;           the command line.                                 |
  198. ;                                                             |
  199. ;           Enter:  ds=PSP seg                                |
  200. ;                                                             |
  201. ;           Exit:  If invalid, carry set and dx=offset msg    |
  202. ;--------------------------------------------------------------
  203.  
  204. get_args        proc    near
  205.                 cld
  206.                 xor     si, si
  207.                 sub     ch, ch
  208.                 mov     cl, [si].arg_len        ;get cmd line length
  209.                 lea     si, [si].arg_off        ;and offset
  210.                 call    skip_white_sp
  211.                 mov     dx, offset es:bad_arg_msg
  212.                 jcxz    get_a800                ;if no args
  213.                 call    get_validate            ;get first i/o port
  214.                 jc      get_a999
  215.                 mov     es:start_port, bx       ;save it
  216.                 call    skip_white_sp
  217.                 jcxz    get_a800                ;if no 2nd arg
  218.                 call    get_validate            ;get 2nd i/o port
  219.                 jc      get_a999
  220.                 mov     es:end_port, bx         ;save it
  221.                 cmp     bx, es:start_port       ;2nd arg >= 1st arg
  222.                 jae     get_a900
  223.                 mov     dx, offset es:bad_2nd_msg
  224.  
  225. get_a800:
  226.                 stc
  227.                 jmp     short get_a999
  228. get_a900:
  229.                 clc
  230. get_a999:
  231.                 ret
  232.  
  233.  
  234. get_args        endp
  235.  
  236.  
  237. ;--------------------------------------------------------------
  238. ;get_validate - Retrieve and validate an ASCII hex number.    |
  239. ;                                                             |
  240. ;              Enter: si ptr to data                          |
  241. ;                     cx max len                              |
  242. ;                                                             |
  243. ;               Exit: data at si now binary                   |
  244. ;                     cx decremented by length of number      |
  245. ;                     If invalid, carry set and dx=&err_msg   |
  246. ;                     bx=binary value of number               |
  247. ;--------------------------------------------------------------
  248. get_validate    proc    near
  249.                 xor     bx, bx
  250. get_v100:
  251.                 cmp     byte ptr [si + bx], ' '
  252.                 je      get_v200
  253.                 cmp     byte ptr [si + bx], CR
  254.                 je      get_v200
  255.                 inc     bx
  256.                 jmp     short get_v100
  257. get_v200:
  258.                 sub     cx, bx                  ;cmd line chars left
  259.                 push    cx
  260.                 mov     cx, bx
  261.                 xor     bx, bx
  262. get_v300:
  263.                 sub     ah, ah
  264.                 lodsb                           ;get a digit
  265.                 call    asc2bin                 ;validate and convert
  266.                 jc      get_v900                ;exit if invalid
  267.                 push    cx
  268.                 jcxz    get_v500
  269.                 dec     cx                      ;position from right - 1
  270.                 shl     cl, 1
  271.                 shl     cl, 1
  272.                 shl     ax, cl                  ;get nibble into position
  273. get_v500:
  274.                 or      bx, ax                  ;build number
  275.                 pop     cx
  276.                 loop    get_v300
  277.                 clc                             ;ok
  278.  
  279. get_v900:
  280.                 pop     cx
  281.                 ret
  282. get_validate    endp
  283.  
  284.  
  285. asc2bin         proc    near
  286.                 cmp     al,  'a'
  287.                 jb      asc2b_100
  288.                 and     al, 0dfh                ;force to upper case
  289. asc2b_100:
  290.                 cmp     al, '0'
  291.                 jb      asc2b_800
  292.                 cmp     al, '9'                 ;see if 0-9 or A-F
  293.                 ja      asc2b_500
  294.                 sub     al, '0'                 ;convert to binary
  295.                 jmp     short asc2b_600
  296. asc2b_500:
  297.                 cmp     al, 'F'
  298.                 ja      asc2b_800
  299.                 sub     al, 'A' - 10
  300. asc2b_600:
  301.                 clc
  302.                 jmp     short asc2b_900
  303. asc2b_800:
  304.                 mov     dx, offset es:bad_arg_msg
  305.                 stc
  306. asc2b_900:
  307.                 ret
  308. asc2bin         endp
  309.  
  310.  
  311.  
  312. skip_white_sp   proc    near
  313.                 cmp     byte ptr [si], ' '
  314.                 je      skip_w200
  315.  
  316.                 cmp     byte ptr [si], TAB
  317.                 je      skip_w200
  318.                 jmp     short skip_w900
  319.  
  320. skip_w200:
  321.                 inc     si
  322.                 loop    skip_white_sp
  323. skip_w900:
  324.                 ret
  325. skip_white_sp   endp
  326.  
  327.  
  328. verify_cpu      proc    near
  329.                 xor     ax,ax
  330.                 push    ax
  331.                 popf
  332.                 pushf
  333.                 pop     ax
  334.                 and     ax,0f000h
  335.                 cmp     ax,0f000h
  336.                 jz      verify_c800     ;not 386
  337.  
  338.                 mov     ax, 0f000h
  339.                 push    ax
  340.                 popf
  341.                 pushf
  342.                 pop     ax
  343.                 and     ax,0f000h       ;not 386
  344.                 jz      verify_c800
  345.  
  346.                 mov     dx,offset noprot_msg
  347.  
  348.                 .386P
  349.                 smsw    ax              ;get pm flag into carry
  350.                 rcr     ax,1
  351.                 jmp     short verify_c999
  352.  
  353. verify_c800:    mov     dx, offset not386_msg
  354.                 stc
  355. verify_c999:
  356.                 ret
  357. verify_cpu      endp
  358.  
  359. setup_ints      proc    near
  360.                 mov     bx, USER_INT
  361.                 mov     di, offset old_user_int
  362.                 mov     cx, isrcode
  363.                 mov     dx, offset isrcode:user_int_isr
  364.                 call    get_int
  365.                 ret
  366. setup_ints      endp
  367.  
  368. ;--------------------------------------------------------------
  369. ;get_int - For a given interrupt vector, store contents and   |
  370. ;          load with new isr address.                         |
  371. ;                                                             |
  372. ;          bx = int number                                    |
  373. ;          es:di = location to store contents                 |
  374. ;          dx = offset new isr                                |
  375. ;          cx = cs of new isr
  376. ;--------------------------------------------------------------
  377. get_int         proc    near
  378.                 cld
  379.                 push    ds
  380.                 xor     ax, ax
  381.                 mov     ds, ax
  382.                 shl     bx, 2
  383.                 mov     ax, [bx]
  384.                 stosw
  385.                 mov     ax, [bx].d_segment
  386.                 stosw
  387.                 cli
  388.                 mov     [bx].d_offset, dx
  389.                 mov     [bx].d_segment, cx
  390.                 sti
  391.                 pop     ds
  392.                 ret
  393. get_int         endp
  394.  
  395.  
  396.  
  397. init_gdt        proc    near
  398.                 mov     ax, gdt_seg
  399.                 mov     ds, ax
  400.                 assume  ds:gdt_seg
  401.  
  402.                 mov     dx, tss_seg
  403.                 movzx   edx, dx                 ;base data segment
  404.                 mov     ecx, (TSS_END - TSS_BEG  ) - 1  ;limit
  405.                 mov     ah, TSS_DESC
  406.                 mov     si, offset sel_tss
  407.                 call    make_entry
  408.  
  409.                 mov     dx, tss_seg
  410.                 movzx   edx, dx                 ;base data segment
  411.                 mov     ecx, (TSS_END - TSS_BEG  ) - 1  ;limit
  412.                 mov     ah, RW_DATA             ;alias as r/w for editing
  413.                 mov     si, offset sel_tss_alias
  414.                 call    make_entry
  415.  
  416.                 mov     dx, gdt_seg
  417.                 movzx   edx, dx                 ;base data segment
  418.                 mov     ecx, (GDT_END - GDT_BEG  ) - 1  ;limit
  419.                 mov     ah, RW_DATA             ;alias as r/w for editing
  420.                 mov     si, offset sel_gdt_alias
  421.                 call    make_entry
  422.  
  423.                 mov     dx, isrcode
  424.                 movzx   edx, dx                 ;base of isr code segment
  425.                 mov     ecx, 0ffffh             ;max segment size
  426.                 mov     ah, ER_CODE
  427.                 mov     si, offset sel_isrcode
  428.                 call    make_entry
  429.  
  430.                 mov     dx, code
  431.                 movzx   edx, dx                 ;base code segment
  432.                 mov     ecx, 0ffffh             ;max segment size
  433.                 mov     ah, ER_CODE
  434.                 mov     si, offset sel_code
  435.                 call    make_entry
  436.  
  437.                 xor     edx, edx                ;zero base
  438.                 mov     ecx, 0fffffh            ;base memory size
  439.                 mov     ah, RW_DATA
  440.                 mov     si, offset sel_databs
  441.                 call    make_entry
  442.  
  443.                 mov     dx, iostack
  444.                 movzx   edx, dx                 ;base stack segment
  445.                 mov     ecx, (STACK_END - STACK_BEG  ) - 1  ;limit
  446.                 mov     ah, RW_DATA
  447.                 mov     si, offset sel_stack
  448.                 call    make_entry
  449.  
  450.                 mov     dx, data
  451.                 movzx   edx, dx                 ;base data segment
  452.                 mov     ecx, (DATA_END - DATA_BEG  ) - 1  ;limit
  453.                 mov     ah, RW_DATA
  454.                 mov     si, offset sel_data
  455.                 call    make_entry
  456.  
  457.                 int     11h                     ;equipment check
  458.                 mov     edx, 0b800h             ;color segment
  459.                 and     al, 30h                 ;monitor bits
  460.                 cmp     al, 30h                 ;30h=monochrome
  461.                 jne     init_gdt500
  462.                 mov     edx, 0b000h             ;monochrome segment
  463.  
  464. init_gdt500:
  465.                 mov     ecx, VID_PAGE_SIZE - 1  ;page size - 1
  466.                 mov     ah, RW_DATA
  467.                 mov     si, offset sel_video
  468.                 call    make_entry
  469.  
  470.                 ret
  471. init_gdt        endp
  472.  
  473. ;--------------------------------------------------------------
  474. ;make_entry - Load a GDT entry from information passed as     |
  475. ;             follows:                                        |
  476. ;                                                             |
  477. ;             ds=gdt segent                                   |
  478. ;             si=offset of gdt entry to load                  |
  479. ;             ah=type | dpl                                   |
  480. ;            ecx=limit                                        |
  481. ;            edx=base segment (convert it to linear)          |
  482. ;            Always set for byte granularity and 16 bit size  |
  483. ;                                                             |
  484. ;--------------------------------------------------------------
  485. make_entry      proc    near
  486.                 shl     edx, 4                  ;convert seg to linear
  487.                 mov     [si].seg_limit_low, cx
  488.                 mov     [si].seg_base_low, dx
  489.                 shr     edx, 16
  490.                 mov     [si].seg_base_mid, dl
  491.                 mov     [si].seg_type_dpl, ah
  492.                 shr     ecx, 16
  493.                 and     cl, 0fh                 ;limit and byte gran
  494.                 mov     [si].seg_limit_gran, cl
  495.                 mov     [si].seg_base_top, dh
  496.  
  497.                 ret
  498. make_entry      endp
  499.  
  500. ;--------------------------------------------------------------
  501. ;init_tss - Initilize TSS with base of I/O bit map and set    |
  502. ;           appropriate bits in I/O bit map per cmd line.     |
  503. ;                                                             |
  504. ;--------------------------------------------------------------
  505. init_tss        proc    near
  506.                 mov     ax, tss_seg
  507.                 mov     ds, ax
  508.                 assume  ds:tss_seg
  509.                 xor     si, si
  510.  
  511.                 mov     ax, offset gdt_seg:sel_stack
  512.                 mov     [si].t_ess0, ax
  513.                 mov     ax, offset iostack:io_sp
  514.                 movzx   eax, ax
  515.                 mov     [si].t_esp0, eax
  516.  
  517.  
  518.                 lea     bx, [si].t_iomap
  519.                 mov     [si].t_iobase, bx
  520.  
  521.                 mov     cx, es:start_port       ;start of range to monitor
  522.                 mov     dx, cx
  523.                 and     cl, 7                   ;get non byte boundary
  524.                 mov     al, 1                   ;first bit position
  525.                 shl     al, cl                  ;get out corresponding bit
  526.                 shr     dx, 3                   ;start_port/8
  527.                 mov     cx, es:end_port
  528.                 sub     cx, es:start_port
  529.                 inc     cx
  530.                 add     bx, dx                  ;starting offset in map
  531. init_t100:
  532.                 or byte ptr [bx], al            ;turn on permission bit
  533.                 rcl     al, 1                   ;next bit position
  534.                 jnc     init_t300
  535.                 inc     bx
  536.                 rcl     al, 1
  537. init_t300:
  538.                 loop    init_t100
  539.  
  540.                 ret
  541. init_tss        endp
  542. code            ends
  543.                 end  start
  544.